Introduction
With the upcoming 2024 United States presidential election
approaching, analysts are consistently searching for metrics to predict
the outcomes accurately and early. While individual voter motivations
are varied and nuanced, a review of the common economic measures in
relation to county election results of the past can potentially provide
insight into the trends of the future. In order to review these
potential trends, the following data was utilized for analysis:
While these datasets include a litany of information, the areas of
focus in this exploratory data analysis are the impacts of county level
unemployment rate for the current election year, county level poverty
rate for the year prior to the current election year, higher education
rate for the four years prior to the current election year. To note,
years prior to the current election year are utilized due to data
availability and the impact of previous year’s socioeconomic conditions
on the current voter’s opinions. The focus of this exploratory data
analysis centers around analyzing potential correlations and predictive
values as related to the 2020 presidential election only.
Relevant Note
All data preparation code is copied in the appendix as well as
included in line with the report, visualization code is only included in
line with the report. To view any of the code in line with each location
it is used in the report, select the Show buttons on the
right hand side of the page.
Visualizing and
Analyzing the Data
Mapping the full
data
For an initial visualization of the data as a whole, the
all.data dataset was mapped by county utilizing an
interactive leaflet map. Due to the size of the dataset and number of
counties, color specific data is not visible until the map is zoomed in
to the appropriate county level. Until zoomed in the color scale (green
to red) represents the number of counties nested in that group until the
map is zoomed in further. Once fully zoomed in the color of the
unnumbered circles (red and blue) represent the winning party
(Republican and Democrat respectively) in each county for the 2020
presidential election.
county_data_raw <- sf::read_sf("https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json") ##pull in map of FIPS codes
FIPSconvert_raw <- sf::read_sf("https://nlepera.github.io/sta551/HW01/data/fips2geocode.csv") ##pull in key of FIPS codes to lat/long
county_data <- county_data_raw %>% #clean county data to list FIPS as numeric & match name to key for join
mutate (id = as.numeric(as.character(id))) %>%
rename (FIPS = id)
FIPSconvert <- FIPSconvert_raw %>%
mutate (fips = as.numeric(as.character(fips)), lon = as.numeric(as.character(lon)), lat = as.numeric(as.character(lat))) %>%
rename (FIPS = fips, Longitude = lon, Latitude = lat)
all.data.join <- full_join(
x = all.data,
y = FIPSconvert,
by = "FIPS",
keep = FALSE
) %>%
ungroup()
Interactive Map of County Data
pal <- colorFactor(c("blue", "red"), domain = c("REPUBLICAN", "DEMOCRAT"))
title <- "
<style>
.custom-title {
color: white;
padding: 0px;
border-radius: 0px;
text-align: right;
}
</style>
Election Results, Education Rates, Unemployment Rates & Poverty Rates
<br>Zoom in to view each county individually
<br>Select a county's circle to view full data"
leaflet() %>%
setView(lng=-98.5795, lat=39.8283, zoom = 4) %>% ##set view to mid US
addProviderTiles(providers$CartoDB.DarkMatter) %>% ##set map to dark mode
addControl(html = title,
position = "topright",
className = "custom-title") %>%
addPolygons(data = county_data, ##add FIPS polygons
color = "yellow",
fill = FALSE,
weight = 0.25) %>%
addCircleMarkers(data = all.data.join,
color = ~pal(party),
radius = 20,
fillOpacity = 0.5,
popup = ~popupTable(all.data),
clusterOptions = markerClusterOptions(maxClusterRadius = 50))
Plot variable
distribution
Before completing any data analysis the distribution of the three
numeric variables of interest was reviewed, controlling for the the
winning party (Republican or Democrat) in each county for the 2020
presidential election.
Both unemployment and higher education rates appear to have normal
distributions while poverty rates appear to have closer to a gamma
distribution. A greater frequency of counties with democratic candidate
winners was seen for all three (3) variables in question.
ggplot (all.data, aes(x = `Unemployment_Rate (%)`, fill = `party`)) +
geom_histogram(inherit.aes = TRUE, color = "black") +
ggtitle ("Distribution of Unemployment Rates by County Election Winner") +
xlab ("County Unemployment Rate (x)
[% of County Pop.]") +
ylab ("Counties W/ Unemployment Rate = x") +
scale_fill_manual(values = c("blue", "red")) +
theme(legend.position = c(0.8, 0.8))

ggplot (all.data, aes(x = `Poverty_Rate (%)`, fill = `party`)) +
geom_histogram(inherit.aes = TRUE, color = "black") +
ggtitle ("Distribution of Poverty Rates by County Election Winner") +
xlab ("County Poverty Rate (x)
[% of County Pop.]") +
ylab ("Counties W/ Poverty Rate = x") +
scale_fill_manual(values = c("blue", "red")) +
theme(legend.position = c(0.8, 0.8), height = "200px")

ggplot (all.data, aes(x = `Higher_Ed_Percent`, fill = `party`)) +
geom_histogram(inherit.aes = TRUE, color = "black") +
ggtitle ("Distribution of Higher Education Rates by County Election Winner") +
xlab ("County Higher Ed. Rate (x)
[% of County Pop.] ") +
ylab ("Counties W/ Higher Ed. Rate = x") +
scale_fill_manual(values = c("blue", "red")) +
theme(legend.position = c(0.8, 0.8))

Plot Relationship
Between Numeric Variables
To determine the potential relationships between the three numeric
variables of interest (Unemployment Rate,
Poverty Rate, and Higher Education Rate) were
plotted against each other and reviewed utilizing a basic linear
regression model for the normally distributed data and a GLM gamma
regresion model for the gamma distributed data.
ggplot(data = all.data, aes(x =all.data$`Unemployment_Rate (%)`, y=all.data$`Poverty_Rate (%)`, color=`party`)) +
geom_point(alpha = 0.25) +
ggtitle ("Unemployment Rates vs. Poverty Rates by Election Winning Party") +
xlab ("County Unemployment Rate [% of County Pop.] (x)") +
ylab ("County Poverty Rate [% of County Pop.] (y)") +
scale_color_manual(values = c("blue", "red")) +
stat_smooth(method = lm, se=FALSE, size = 0.1)

pov_unem <- lm(`Poverty_Rate (%)`~`Unemployment_Rate (%)` , data = all.data)
summary(pov_unem)
Call:
lm(formula = `Poverty_Rate (%)` ~ `Unemployment_Rate (%)`, data = all.data)
Residuals:
Min 1Q Median 3Q Max
-21.355 -3.713 -0.826 2.871 34.731
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 9.40945 0.30570 30.78 <2e-16 ***
`Unemployment_Rate (%)` 0.74165 0.04289 17.29 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 5.519 on 3189 degrees of freedom
(128 observations deleted due to missingness)
Multiple R-squared: 0.08572, Adjusted R-squared: 0.08544
F-statistic: 299 on 1 and 3189 DF, p-value: < 2.2e-16
ggplot(data = all.data, aes(x =all.data$`Higher_Ed_Percent`, y=all.data$`Poverty_Rate (%)`, color=`party`)) +
geom_point(alpha = 0.25) +
ggtitle ("Percent of Population w/ Higher Education vs.
Poverty Rates by Election Winning Party") +
xlab ("County Higher Ed. Rate [% of County Pop.] (x)") +
ylab ("County Poverty Rate [% of County Pop.] (y)") +
scale_color_manual(values = c("blue", "red")) +
stat_smooth(method = glm, se=FALSE, size = 0.1)

highed_pov <- glm(`Higher_Ed_Percent`~`Poverty_Rate (%)`, data = all.data)
summary(highed_pov)
Call:
glm(formula = Higher_Ed_Percent ~ `Poverty_Rate (%)`, data = all.data)
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 68.37787 0.41629 164.26 <2e-16 ***
`Poverty_Rate (%)` -1.07151 0.02681 -39.97 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for gaussian family taken to be 76.33665)
Null deviance: 365417 on 3190 degrees of freedom
Residual deviance: 243438 on 3189 degrees of freedom
(128 observations deleted due to missingness)
AIC: 22893
Number of Fisher Scoring iterations: 2
ggplot(data = all.data, aes(x =all.data$`Higher_Ed_Percent`, y=all.data$`Unemployment_Rate (%)`, color=`party`)) +
geom_point(alpha = 0.25) +
ggtitle ("Percent of Population w/ Higher Education vs.
Unemployment Rates by Election Winning Party") +
xlab ("County Higher Ed. Rate [% of County Pop.] (x)") +
ylab ("County Unemployment Rate [% of County Pop.] (y)") +
scale_color_manual(values = c("blue", "red")) +
stat_smooth(method = lm, se=FALSE, size = 0.1)

highed_unem <- lm(`Higher_Ed_Percent`~`Unemployment_Rate (%)`, data = all.data)
summary(highed_unem)
Call:
lm(formula = Higher_Ed_Percent ~ `Unemployment_Rate (%)`, data = all.data)
Residuals:
Min 1Q Median 3Q Max
-47.747 -7.579 -0.476 6.880 36.109
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 59.02069 0.56472 104.51 <2e-16 ***
`Unemployment_Rate (%)` -0.92418 0.07816 -11.82 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 10.51 on 3268 degrees of freedom
(49 observations deleted due to missingness)
Multiple R-squared: 0.04102, Adjusted R-squared: 0.04073
F-statistic: 139.8 on 1 and 3268 DF, p-value: < 2.2e-16
Conclusions
While all three investigated potential correlations indicated a high
level of statistic significance with p values well below 0.05, both the
Unemployment Rates vs. Poverty Rates by Election Winning Party
and
Percent of Population w/ Higher Education vs. Unemployment Rates by Election Winning Party
models illustrated a poor fit with very low R squared values. The
Percent of Population w/ Higher Education vs. Poverty Rates by Election Winning Party
also illustrated a poor fit but had the highest r squared value
indicating reduced variance in this model. No clustering was noted along
the party variables.
Overall a correlation between unemployment rates, poverty rates,
higher education rates, and county winning party was not
illustrated.
LS0tDQp0aXRsZTogIlByZXNpZGVudGlhbCBGaXRuZXNzIFRlc3Q6PGltZyBzcmM9XCJodHRwczovL25sZXBlcmEuZ2l0aHViLmlvL3N0YTU1MS9IVzAxL2ltZy9wZW5ndWluX2N1dGUucG5nXCIgc3R5bGU9XCJmbG9hdDogcmlnaHQ7IHdpZHRoOiAxMiVcIi8+Ig0Kc3VidGl0bGU6ICJUaGUgSW1wYWN0IG9mIExvY2FsIEVkdWNhdGlvbiwgUG92ZXJ0eSwgYW5kIFVuZW1wbG95bWVudCBSYXRlcyBvbiBDb3VudHkgUHJlc2lkZW50YWwgRWxlY3Rpb24gUmVzdWx0cyINCmF1dGhvcjogDQotIG5hbWU6IE5hdGFsaWUgTGVQZXJhDQogIGFmZmlsaWF0aW9uOiBXZXN0IENoZXN0ZXIgVW5pdmVyc2l0eSB8IFNUQTUxMSAtIEhXIDAxDQpkYXRlOiAiMjUgU2VwIDIwMjQiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAyDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICB0b2NfY29sbGFwc2U6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICAgIHRoZW1lOiByZWFkYWJsZQ0KLS0tDQoNCmBgYHtjc3MgZWNobyA9IEZBTFNFfQ0KaDEudGl0bGUgeyAgLyogVGl0bGUgLSBmb250IHNwZWNpZmljYXRpb25zIG9mIHRoZSByZXBvcnQgdGl0bGUgKi8NCiAgZm9udC13ZWlnaHQ6Ym9sZDsNCiAgY29sb3I6IGRhcmttYWdlbnRhIDsNCn0NCmgxLnN1YnRpdGxlIHsgIC8qIFRpdGxlIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBvZiB0aGUgcmVwb3J0IHRpdGxlICovDQogIGZvbnQtd2VpZ2h0OmJvbGQ7DQogIGNvbG9yOiBkYXJrbWFnZW50YSA7DQp9DQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgZm9yIGF1dGhvcnMgICovDQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBuYXZ5Ow0KfQ0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgdGhlIGRhdGUgICovDQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBuYXZ5Ow0KfQ0KaDEgeyAvKiBIZWFkZXIgMSAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgZm9yIGxldmVsIDEgc2VjdGlvbiB0aXRsZSAgKi8NCiAgICBmb250LXdlaWdodDpib2xkOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQpoMiB7IC8qIEhlYWRlciAyIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMiBzZWN0aW9uIHRpdGxlICovDQogICAgZm9udC13ZWlnaHQ6Ym9sZDsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBvZiBsZXZlbCAzIHNlY3Rpb24gdGl0bGUgICovDQogICAgZm9udC13ZWlnaHQ6Ym9sZDsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoNCB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBvZiBsZXZlbCA0IHNlY3Rpb24gdGl0bGUgICovDQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KYm9keSB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0NCg0KcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCmg1IHsNCiAgY29sb3I6IHdoaXRlOw0KfQ0KDQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQppZiAoIXJlcXVpcmUoImRwbHlyIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJkcGx5ciIpDQp9DQoNCmlmICghcmVxdWlyZSgic3RyaW5nciIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygic3RyaW5nciIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJzdHJpbmdyIikNCn0NCg0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJwbG90bHkiKQ0KfQ0KDQppZiAoIXJlcXVpcmUoImxlYWZsZXQiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImxlYWZsZXQiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgibGVhZmxldCIpDQp9DQoNCmlmICghcmVxdWlyZSgiY3Jvc3N0YWxrIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJjcm9zc3RhbGsiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiY3Jvc3N0YWxrIikNCn0NCg0KDQppZiAoIXJlcXVpcmUoInJqc29uIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJyanNvbiIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJyanNvbiIpDQp9DQppZiAoIXJlcXVpcmUoInRpZ3JpcyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygidGlncmlzIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoInRpZ3JpcyIpDQp9DQppZiAoIXJlcXVpcmUoInJhc3RlciIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygicmFzdGVyIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoInJhc3RlciIpDQp9DQppZiAoIXJlcXVpcmUoImxlYWZwb3AiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImxlYWZwb3AiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgibGVhZnBvcCIpDQp9DQppZiAoIXJlcXVpcmUoImdncmlkZ2VzIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3JpZGdlcyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJnZ3JpZGdlcyIpDQp9DQppZiAoIXJlcXVpcmUoImNvd3Bsb3QiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImNvd3Bsb3QiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiY293cGxvdCIpDQp9DQoNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFRSVUUsICAgDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQSkNCg0Kb3B0aW9ucyhEVC5vcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gNSwgc2Nyb2xsWCA9IFRSVUUpKQ0KYGBgDQo8YnI+DQoNCiMgSW50cm9kdWN0aW9uDQoNCldpdGggdGhlIHVwY29taW5nIDIwMjQgVW5pdGVkIFN0YXRlcyBwcmVzaWRlbnRpYWwgZWxlY3Rpb24gYXBwcm9hY2hpbmcsIGFuYWx5c3RzIGFyZSBjb25zaXN0ZW50bHkgc2VhcmNoaW5nIGZvciBtZXRyaWNzIHRvIHByZWRpY3QgdGhlIG91dGNvbWVzIGFjY3VyYXRlbHkgYW5kIGVhcmx5LiAgV2hpbGUgaW5kaXZpZHVhbCB2b3RlciBtb3RpdmF0aW9ucyBhcmUgdmFyaWVkIGFuZCBudWFuY2VkLCBhIHJldmlldyBvZiB0aGUgY29tbW9uIGVjb25vbWljIG1lYXN1cmVzIGluIHJlbGF0aW9uIHRvIGNvdW50eSBlbGVjdGlvbiByZXN1bHRzIG9mIHRoZSBwYXN0IGNhbiBwb3RlbnRpYWxseSBwcm92aWRlIGluc2lnaHQgaW50byB0aGUgdHJlbmRzIG9mIHRoZSBmdXR1cmUuICAgSW4gb3JkZXIgdG8gcmV2aWV3IHRoZXNlIHBvdGVudGlhbCB0cmVuZHMsIHRoZSBmb2xsb3dpbmcgZGF0YSB3YXMgdXRpbGl6ZWQgZm9yIGFuYWx5c2lzOg0KDQotIFByZXNpZGVudGlhbCBFbGVjdGlvbiBEYXRhLCBvYnRhaW5lZCBmcm9tIHRoZSBwdWJsaWNseSBhdmFpbGFibGUgPGEgaHJlZj0iaHR0cHM6Ly9lbGVjdGlvbmxhYi5taXQuZWR1L2RhdGEiPk1JVCBFbGVjdGlvbiBMYWIgRGF0YSBTZXRzPC9hPg0KLSBQZXIgQ291bnR5IFVuZW1wbG95bWVudCBEYXRhLCBvYnRhaW5lZCBmcm9tIHRoZSBwdWJsaWNseSBhdmFpbGFibGUgPGEgaHJlZj0iaHR0cHM6Ly93d3cuZXJzLnVzZGEuZ292L2RhdGEtcHJvZHVjdHMvY291bnR5LWxldmVsLWRhdGEtc2V0cy8iPlVTREEgRWNvbm9taWMgUmVzZWFyY2ggU2VydmljZSBDb3VudHktbGV2ZWwgZGF0YXNldHM8L2E+DQotIFBlciBDb3VudHkgUG92ZXJ0eSBEYXRhLCBvYnRhaW5lZCBmcm9tIHRoZSBwdWJsaWNseSBhdmFpbGFibGUgPGEgaHJlZj0iaHR0cHM6Ly93d3cuZXJzLnVzZGEuZ292L2RhdGEtcHJvZHVjdHMvY291bnR5LWxldmVsLWRhdGEtc2V0cy8iPlVTREEgRWNvbm9taWMgUmVzZWFyY2ggU2VydmljZSBDb3VudHktbGV2ZWwgZGF0YXNldHM8L2E+DQotIFBlciBDb3VudHkgRWR1Y2F0aW9uIERhdGEsIG9idGFpbmVkIGZyb20gdGhlIHB1YmxpY2x5IGF2YWlsYWJsZSA8YSBocmVmPSJodHRwczovL3d3dy5lcnMudXNkYS5nb3YvZGF0YS1wcm9kdWN0cy9jb3VudHktbGV2ZWwtZGF0YS1zZXRzLyI+VVNEQSBFY29ub21pYyBSZXNlYXJjaCBTZXJ2aWNlIENvdW50eS1sZXZlbCBkYXRhc2V0czwvYT4NCg0KDQpXaGlsZSB0aGVzZSBkYXRhc2V0cyBpbmNsdWRlIGEgbGl0YW55IG9mIGluZm9ybWF0aW9uLCB0aGUgYXJlYXMgb2YgZm9jdXMgaW4gdGhpcyBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIGFyZSB0aGUgaW1wYWN0cyBvZiBjb3VudHkgbGV2ZWwgdW5lbXBsb3ltZW50IHJhdGUgZm9yIHRoZSBjdXJyZW50IGVsZWN0aW9uIHllYXIsIGNvdW50eSBsZXZlbCBwb3ZlcnR5IHJhdGUgZm9yIHRoZSB5ZWFyIHByaW9yIHRvIHRoZSBjdXJyZW50IGVsZWN0aW9uIHllYXIsIGhpZ2hlciBlZHVjYXRpb24gcmF0ZSBmb3IgdGhlIGZvdXIgeWVhcnMgcHJpb3IgdG8gdGhlIGN1cnJlbnQgZWxlY3Rpb24geWVhci4gIFRvIG5vdGUsIHllYXJzIHByaW9yIHRvIHRoZSBjdXJyZW50IGVsZWN0aW9uIHllYXIgYXJlIHV0aWxpemVkIGR1ZSB0byBkYXRhIGF2YWlsYWJpbGl0eSBhbmQgdGhlIGltcGFjdCBvZiBwcmV2aW91cyB5ZWFyJ3Mgc29jaW9lY29ub21pYyBjb25kaXRpb25zIG9uIHRoZSBjdXJyZW50IHZvdGVyJ3Mgb3BpbmlvbnMuICBUaGUgZm9jdXMgb2YgdGhpcyBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIGNlbnRlcnMgYXJvdW5kIGFuYWx5emluZyBwb3RlbnRpYWwgY29ycmVsYXRpb25zIGFuZCBwcmVkaWN0aXZlIHZhbHVlcyBhcyByZWxhdGVkIHRvIHRoZSAyMDIwIHByZXNpZGVudGlhbCBlbGVjdGlvbiBvbmx5LiANCg0KPGg0PlJlbGV2YW50IE5vdGU8L2g0Pg0KQWxsIGRhdGEgcHJlcGFyYXRpb24gY29kZSBpcyBjb3BpZWQgaW4gdGhlIGFwcGVuZGl4IGFzIHdlbGwgYXMgaW5jbHVkZWQgaW4gbGluZSB3aXRoIHRoZSByZXBvcnQsIHZpc3VhbGl6YXRpb24gY29kZSBpcyBvbmx5IGluY2x1ZGVkIGluIGxpbmUgd2l0aCB0aGUgcmVwb3J0LiBUbyB2aWV3IGFueSBvZiB0aGUgY29kZSBpbiBsaW5lIHdpdGggZWFjaCBsb2NhdGlvbiBpdCBpcyB1c2VkIGluIHRoZSByZXBvcnQsIHNlbGVjdCB0aGUgYFNob3dgIGJ1dHRvbnMgb24gdGhlIHJpZ2h0IGhhbmQgc2lkZSBvZiB0aGUgcGFnZS4NCg0KIyBEYXRhIFByZXBhcmF0aW9uDQoNClByaW9yIHRvIGFueSBkYXRhIHZpc3VhbGl6YXRpb24gYW5kIGFuYWx5c2lzLCBhbGwgZGF0YXNldHMgd2VyZSBsb2FkZWQgaW50byBSU3R1ZGlvICh2MjAyNC4wOS4wIEJ1aWxkIDM3NSkgdG8gcHJlcGFyZSB1bmlxdWUgcmVsYWlvbmFsIGRhdGFzZXRzLiAgQSB1bmlxdWUgaWRlbnRpZmllciBvZiBgRklQUyBDb2RlYCB3YXMgdXRpbGl6ZWQgYWNyb3NzIGFsbCBmb3VyICg0KSBkYXRhc2V0cywgYXMgd2VsbCBhcyB0byBsaW5rIHRoZSByZWxldmFudCBnZW9KU09OIGRhdGEgZm9yIGNvdW50eSBtYXBwaW5nLiANCg0KIyMgQ3JlYXRlIFJlbGF0aW9uYWwgRGF0YXNldHMNCg0KIyMjIFByZXNpZGVudGlhbCBFbGVjdGlvbiBEYXRhICgyMDIwIG9yIG1vc3QgcmVjZW50IHllYXIgYXZhaWxhYmxlKQ0KDQpUaGUgcmF3IHByZXNpZGVudGlhbCBlbGVjdGlvbiBkYXRhIHdhcyBvYnRhaW5lZCBmcm9tIGZyb20gdGhlIHB1YmxpY2x5IGF2YWlsYWJsZSA8YSBocmVmPSJodHRwczovL2RhdGF2ZXJzZS5oYXJ2YXJkLmVkdS9kYXRhc2V0LnhodG1sP3BlcnNpc3RlbnRJZD1kb2k6MTAuNzkxMC9EVk4vVk9RQ0hRIj5NSVQgRWxlY3Rpb24gTGFiIERhdGEgU2V0OiBDb3VudHkgUHJlc2lkZW50aWFsIEVsZWN0aW9uIFJldHVybnMgMjAwMC0yMDIwPC9hPi4gDQoNCkVsZWN0aW9uIGRhdGEgd2FzIHJlYWQgaW50byBSU3R1ZGlvIGFzIGBlbGVjdGlvbl9yYXdgIGFuZCBjbGVhbmVkIHV0aWxpemluZyB0aGUgZm9sbG93aW5nIHN0ZXBzIHRvIGNyZWF0ZSB0aGUgcmVsYXRpb25hbCBkYXRhc2V0IGBlbGVjdGlvbmA6DQoNCi0gRGF0YSB3YXMgZ3JvdXBlZCBieSB0aGUgY291bnR5IGBGSVBTIGNvZGVgDQotIERhdGEgd2FzIHNvcnRlZCBieSBkZXNjZW5kaW5nIGBZZWFyYA0KLSBEYXRhIHdhcyBmaWx0ZXJlZCBieSBwb2xpdGljYWwgYFBhcnR5YCBmb3Igb25seSBgRGVtb2NyYXRgIGFuZCBgUmVwdWJsaWNhbmAgYXMgdGhlIGFuYWx5c2lzIGZvY3VzZXMgb24gdGhlIHBvdGVudGlhbCBpbXBhY3RzIG9uIGNvdW50eSBwcmVzaWRlbnRpYWwgZWxlY3Rpb24gd2lubmVycy4gIE5vIG90aGVyIHBhcnRpZXMgaGF2ZSBldmVyIHdvbiB0aGUgcHJlc2lkZW5jeSBhbmQgdGh1cyB3ZXJlIG9taXR0ZWQuICANCiAgLSBUbyBub3RlOiBibGFuayB2YWx1ZXMgd2VyZSBub3Qgb21pdHRlZA0KLSBVbm5lY2Vzc2FyeSB2YXJpYWJsZXMgd2VyZSByZW1vdmVkDQotIERhdGEgd2FzIGZpbHRlcmVkIGZvciBgMjAyMGAgb3IgdGhlIGBtb3N0IHJlY2VudCB5ZWFyIHdpdGggYXZhaWxhYmxlIGRhdGFgIGlmIDIwMjAgd2FzIG5vdCBhdmFpbGFibGUNCg0KQSBzZWFyY2hhYmxlIHByZXZpZXcgb2YgdGhlIHJlbGF0aW9uYWwgZGF0YXNldCBgZWxlY3Rpb25gIGlzIGF2YWlsYWJsZSBpbiB0aGUgZGF0YSB0YWJsZSBiZWxvdy4gIA0KDQpgYGB7cn0NCiMjcmVhZCBpbiB0aGUgZWxlY3Rpb24gZGF0YSBhcyBlbGVjdGlvbl9yYXcNCg0KZWxlY3Rpb25fcmF3IDwtIHJlYWQuY3N2KCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vbmxlcGVyYS9zdGE1NTEvcmVmcy9oZWFkcy9tYWluL0hXMDEvZGF0YS9jb3VudHlwcmVzaWRlbnRpYWxfZWxlY3Rpb25fMjAwMC0yMDIwLmNzdicpDQoNCiMjY2xlYW4gdGhlIGVsZWN0aW9uIGRhdGEgDQoNCmVsZWN0aW9uIDwtIGVsZWN0aW9uX3JhdyAlPiUgDQogIGdyb3VwX2J5KGNvdW50eV9maXBzKSAlPiUgICAjI2dyb3VwIGJ5IGNvdW50eSBGSVBTIGNvZGUNCiAgYXJyYW5nZSAoZGVzYyh5ZWFyKSkgJT4lICAgICMjc29ydCBieSBkZXNjZW5kaW5nIHllYXINCiAgZmlsdGVyIChwYXJ0eSA9PSAiREVNT0NSQVQiIHwgcGFydHkgPT0gIlJFUFVCTElDQU4iKSAlPiUgICAgIyNmaWx0ZXIgZm9yIG9ubHkgZGVtICYgcmVwDQogIHN1YnNldCgsIC1jKHN0YXRlX3BvLCBvZmZpY2UsIHZlcnNpb24sIG1vZGUpKSAlPiUgICAjI3JlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW5zDQogIHNsaWNlICgxOjIpICU+JSAgICMjcHVsbCB0b3AgMiB2YWx1ZXMgZm9yIGVhY2ggZ3JvdXAgKGNvdW50eV9maXBzIHNvcnRlZCBieSBkZXNjIHllYXIpIHB1bGxpbmcgYm90aCBkZW0gJiByZXAgZm9yIGVhY2ggY291bnR5IGF0IG1heCB5ZWFyIGF2YWlsYWJsZQ0KICBhcnJhbmdlIChkZXNjKGNhbmRpZGF0ZXZvdGVzKSkgJT4lICAgICMjcmUgZmlsdGVyIHRvIHNvcnQgYnkgZ3JvdXAsIHdpdGggaGlnaGVzdCBjYW5kaWRhdGUgdm90ZXMgb24gdG9wDQogIHNsaWNlICgxKSAlPiUgICAgIyNvbmx5IGtlZXAgdmFsdWUgZm9yIGhpZ2hlc3QgY2FuZGlkYXRlIHZvdGVzICh3aW5uZXIpIHBlciBjb3VudHkNCiAgcmVuYW1lIChGSVBTID0gY291bnR5X2ZpcHMpICAgIyMgc2V0IElEIG5hbWUgZm9yIG91dGVyIGpvaW4NCiAgDQpEVDo6ZGF0YXRhYmxlKGVsZWN0aW9uKQ0KYGBgDQoNCiMjIyBVbmVtcGxveW1lbnQgRGF0YSAoMjAyMCBvciBtb3N0IHJlY2VudCB5ZWFyIGF2YWlsYWJsZSkNClRoZSByYXcgdW5lbXBsb3ltZW50IGRhdGEgd2FzIG9idGFpbmVkIGZyb20gZnJvbSB0aGUgcHVibGljbHkgYXZhaWxhYmxlIDxhIGhyZWY9Imh0dHBzOi8vd3d3LmVycy51c2RhLmdvdi9kYXRhLXByb2R1Y3RzL2NvdW50eS1sZXZlbC1kYXRhLXNldHMvIj5VU0RBIEVjb25vbWljIFJlc2VhcmNoIFNlcnZpY2UgQ291bnR5LWxldmVsIERhdGFzZXQ6IFVuZW1wbG95bWVudDwvYT4uIA0KDQpVbmVtcGxveW1lbnQgZGF0YSB3YXMgcmVhZCBpbnRvIFJTdHVkaW8gYXMgYHVuZW1wbG95X3Jhd2AgYW5kIGNsZWFuZWQgdXRpbGl6aW5nIHRoZSBmb2xsb3dpbmcgc3RlcHMgdG8gY3JlYXRlIHRoZSByZWxhdGlvbmFsIGRhdGFzZXQgYHVuZW1wbG95YDoNCg0KLSBEYXRhIHdhcyBmaWx0ZXJlZCBmb3IgdGV4dCBjb250YWluaW5nIHRoZSBzdHJpbmcgYFVuZW1wbG95bWVudGAgaW4gdGhlIGBBdHRyaWJ1dGVgIHZhcmlhYmxlIGRhdGEgdmFsdWVzIHRvIHJlbW92ZSBvdGhlciB1bm5lY2Vzc2FyeSBkYXRhIHR5cGVzLg0KLSBJbiBvcmRlciB0byBleHRyYWN0IHRoZSB5ZWFyIGZyb20gdGhlIGBBdHRyaWJ1dGVgIHZhbHVlcywgYSBuZXcgY29sdW1uIHdhcyBjcmVhdGVkIGJ5IGV4dHJhY3RpbmcgdGhlIGxhc3QgZm91ciAoNCkgY2hhcmFjdGVycyBvZiB0aGUgYEF0dHJpYnV0ZWAgdmFsdWVzLg0KLSBEYXRhIHdhcyBncm91cGVkIGJ5IHRoZSBjb3VudHkgYEZJUFMgY29kZWANCi0gRGF0YSB3YXMgc29ydGVkIGJ5IGRlc2NlbmRpbmcgYFllYXJgDQotIERhdGEgd2FzIGZpbHRlcmVkIGZvciBgMjAyMGAgb3IgdGhlIGBtb3N0IHJlY2VudCB5ZWFyIHdpdGggYXZhaWxhYmxlIGRhdGFgIGlmIDIwMjAgd2FzIG5vdCBhdmFpbGFibGUNCi0gVW5uZWNlc3NhcnkgdmFyaWFibGVzIHdlcmUgcmVtb3ZlZA0KDQpBIHNlYXJjaGFibGUgcHJldmlldyBvZiB0aGUgcmVsYXRpb25hbCBkYXRhc2V0IGB1bmVtcGxveWAgaXMgYXZhaWxhYmxlIGluIHRoZSBkYXRhIHRhYmxlIGJlbG93LiAgDQoNCmBgYHtyfQ0KIyMgcmVhZCBpbiB0aGUgdW5lbXBsb3ltZW50IGRhdGEgYXMgdW5lbXBsb3lfcmF3DQoNCnVuZW1wbG95X3JhdyA8LSByZWFkLmNzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL25sZXBlcmEvc3RhNTUxL3JlZnMvaGVhZHMvbWFpbi9IVzAxL2RhdGEvVW5lbXBsb3ltZW50LmNzdicpDQoNCiMjIGNsZWFuIHRoZSB1bmVtcGxveW1lbnQgZGF0YQ0KdW5lbXBsb3kgPC0gdW5lbXBsb3lfcmF3ICU+JSANCiAgZmlsdGVyIChncmVwbCgnVW5lbXBsb3ltZW50JywgQXR0cmlidXRlKSkgJT4lICAgI3VzZSBkcGx5ciBwYWNrYWdlIHRvIHVzZSBmaWx0ZXIoZ3JlcGwoKSkgdG8gZmlsdGVyIGZvciBzdHJpbmcgb2YgdGV4dCB0byBzZWxlY3Qgb25seSB0aGUgdW5lbXBsb3ltZW50IHJhdGUgdmFsdWVzDQogIG11dGF0ZSAoeWVhciA9IHN0cl9zdWIoQXR0cmlidXRlLCAtNCkpICU+JSAgIyNjcmVhdGUgYSBuZXcgY29sdW1uIHVzaW5nIG11dGF0ZSBhbmQgc3RyaW5nciB0byBjcmVhdGUgYSBuZXcgY29sdW1uIGZyb20gdGhlIGxhc3QgNCB2YWx1ZXMgb2YgdGhlIGF0dHJpYnV0ZSBjb2x1bW4sIHRvIGV4dHJhY3QgdGhlIHllYXIgKHN0cl9zdWIgLT4gc3RyaW5ncl9zdWJzZXQpDQogIGdyb3VwX2J5IChGSVBTX0NvZGUpICU+JSAgIyNncm91cCBieSBGSVBTIGNvZGUgYmVmb3JlIHNvcnRpbmcgdG8gZ2V0IG1heCB5ZWFyDQogIGFycmFuZ2UgKGRlc2MoeWVhcikpICU+JSAgIyMgc29ydCBkZXNjZW5kaW5nIHllYXIgdG8gcHV0IG1heCBhdmFpbGFibGUgYXQgdGhlIHRvcA0KICBzbGljZSgxKSAlPiUgICAjI3NsaWNlIHRvcCB2YWx1ZSB0byBrZWVwIG9ubHkgbWF4IHllYXIgZm9yIGVhY2ggRklQUyBjb2RlDQogIHN1YnNldCAoLCBjKEZJUFNfQ29kZSwgVmFsdWUpKSAlPiUgICAjI3JlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW5zDQogIHJlbmFtZSAoIlVuZW1wbG95bWVudF9SYXRlICglKSIgPSBWYWx1ZSwgRklQUyA9IEZJUFNfQ29kZSkgICAgIyNyZW5hbWUgY29sdW1uIHRvIHJlZmxlY3QgdW5lbXBsb3ltZW50IHJhdGUgJiBzZXQgSUQgbmFtZSBmb3Igb3V0ZXIgam9pbg0KDQpEVDo6ZGF0YXRhYmxlKHVuZW1wbG95KQ0KICANCmBgYA0KDQojIyMgUG92ZXJ0eSBEYXRhICgyMDE5KQ0KVGhlIHJhdyBwb3ZlcnR5IGRhdGEgd2FzIG9idGFpbmVkIGZyb20gZnJvbSB0aGUgcHVibGljbHkgYXZhaWxhYmxlIDxhIGhyZWY9Imh0dHBzOi8vd3d3LmVycy51c2RhLmdvdi9kYXRhLXByb2R1Y3RzL2NvdW50eS1sZXZlbC1kYXRhLXNldHMvIj5VU0RBIEVjb25vbWljIFJlc2VhcmNoIFNlcnZpY2UgQ291bnR5LWxldmVsIERhdGFzZXQ6IFBvdmVydHk8L2E+LiANCg0KUG92ZXJ0eSBkYXRhIHdhcyByZWFkIGludG8gUlN0dWRpbyBhcyBgcG92ZXJ0eV9yYXdgIGFuZCBjbGVhbmVkIHV0aWxpemluZyB0aGUgZm9sbG93aW5nIHN0ZXBzIHRvIGNyZWF0ZSB0aGUgcmVsYXRpb25hbCBkYXRhc2V0IGBwb3ZlcnR5YDoNCg0KLSBEYXRhIHdhcyBmaWx0ZXJlZCBmb3IgdGV4dCBjb250YWluaW5nIHRoZSBzdHJpbmcgYFBDVFBPVkFMTF8yMDE5YCBpbiB0aGUgYEF0dHJpYnV0ZWAgdmFyaWFibGUgZGF0YSB2YWx1ZXMgdG8gcmVtb3ZlIG90aGVyIHVubmVjZXNzYXJ5IGRhdGEgdHlwZXMuDQotIFVubmVjZXNzYXJ5IHZhcmlhYmxlcyB3ZXJlIHJlbW92ZWQNCg0KQSBzZWFyY2hhYmxlIHByZXZpZXcgb2YgdGhlIHJlbGF0aW9uYWwgZGF0YXNldCBgdW5lbXBsb3lgIGlzIGF2YWlsYWJsZSBpbiB0aGUgZGF0YSB0YWJsZSBiZWxvdy4NCg0KYGBge3J9DQojIyByZWFkIGluIHRoZSBwb3ZlcnR5IGRhdGEgYXMgcG92ZXJ0eV9yYXcNCg0KcG92ZXJ0eV9yYXcgPC0gcmVhZC5jc3YoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9ubGVwZXJhL3N0YTU1MS9yZWZzL2hlYWRzL21haW4vSFcwMS9kYXRhL1BvdmVydHlFc3RpbWF0ZXMuY3N2JykNCg0KIyNjbGVhbiB0aGUgcG92ZXJ0eSBkYXRhDQpwb3ZlcnR5IDwtIHBvdmVydHlfcmF3ICU+JSANCiAgZmlsdGVyIChBdHRyaWJ1dGUgPT0gIlBDVFBPVkFMTF8yMDE5IikgJT4lICAjI0ZpbHRlciBmb3IgMjAxOSBwb3ZlcnR5IHZhbHVlcw0KICBzdWJzZXQgKCwgYyhGSVBTdHh0LCBWYWx1ZSkpICU+JSAgIyNyZW1vdmUgdW5uZWNjZXNzYXJ5IGNvbHVtbnMNCiAgcmVuYW1lICgiUG92ZXJ0eV9SYXRlICglKSIgPSBWYWx1ZSwgRklQUyA9IEZJUFN0eHQpICAgIyNyZW5hbWUgVmFsdWUgY29sdW1uIHRvIFBvdmVydHlfUmF0ZSAoJSkgYW5kIHNldCBJRCBuYW1lIGZvciBvdXRlciBqb2luDQoNCkRUOjpkYXRhdGFibGUocG92ZXJ0eSkNCmBgYA0KDQojIyMgRWR1Y2F0aW9uIERhdGEgKDIwMTUgLSAyMDE5KQ0KVGhlIHJhdyBlZHVjYXRpb24gZGF0YSB3YXMgb2J0YWluZWQgZnJvbSBmcm9tIHRoZSBwdWJsaWNseSBhdmFpbGFibGUgPGEgaHJlZj0iaHR0cHM6Ly93d3cuZXJzLnVzZGEuZ292L2RhdGEtcHJvZHVjdHMvY291bnR5LWxldmVsLWRhdGEtc2V0cy8iPlVTREEgRWNvbm9taWMgUmVzZWFyY2ggU2VydmljZSBDb3VudHktbGV2ZWwgRGF0YXNldDogRWR1Y2F0aW9uPC9hPi4gDQoNClVuZW1wbG95bWVudCBkYXRhIHdhcyByZWFkIGludG8gUlN0dWRpbyBhcyBgZWR1X3Jhd2AgYW5kIGNsZWFuZWQgdXRpbGl6aW5nIHRoZSBmb2xsb3dpbmcgc3RlcHMgdG8gY3JlYXRlIHRoZSByZWxhdGlvbmFsIGRhdGFzZXQgYGVkdWA6DQoNCi0gVW5uZWNlc3NhcnkgdmFyaWFibGVzIHdlcmUgcmVtb3ZlZA0KLSBDb2x1bW5zIHdlcmUgcmVuYW1lZCB0byB0cnVuY2F0ZWQgdmFsdWVzIGZvciBlYXNlIG9mIHVzZToNCiAgLSBgTm9fSFNgID0gIyBvZiBwZXJzb25zIGluIHRoZSBjb3VudHkgd2l0aCBsZXNzIHRoYW4gYSBoaWdoIHNjaG9vbCBkaXBsb21hDQogIC0gYEhTYCA9ICMgb2YgcGVyc29ucyBpbiB0aGUgY291bnR5IHdpdGggYSBoaWdoIHNjaG9vbCBkaXBsb21hIG9ubHkNCiAgLSBgQVNfU29tZUNvbGAgPSAjIG9mIHBlcnNvbnMgaW4gdGhlIGNvdW50eSB3aXRoIGVpdGhlciBzb21lIGNvbGxlZ2UgY3JlZGl0IG9yIGFuIEFzc29jaWF0ZSdzIERlZ3JlZQ0KICAtIGBCU19Nb3JlYCA9ICMgb2YgcGVyc29ucyBpbiB0aGUgY291bnR5IHdpdGggYSBCYWNoZWxvcidzIERlZ3JlZSBvciBoaWdoZXINCi0gRGF0YSBjbGVhbmVkIHRvIHJlbW92ZSBjb21tYXMgZnJvbSBudW1iZXJzIGFuZCBjb252ZXJ0IGZyb20gY2hhcmFjdGVyIHRvIG51bWVyaWMgdmFsdWVzDQoNCg0KQSBzZWFyY2hhYmxlIHByZXZpZXcgb2YgdGhlIHJlbGF0aW9uYWwgZGF0YXNldCBgdW5lbXBsb3lgIGlzIGF2YWlsYWJsZSBpbiB0aGUgZGF0YSB0YWJsZSBiZWxvdy4NCg0KDQpgYGB7cn0NCiMjIHJlYWQgaW4gdGhlIHVuZW1wbG95bWVudCBkYXRhIGFzIGVkdV9yYXcNCg0KZWR1X3JhdyA8LSByZWFkLmNzdignaHR0cHM6Ly9ubGVwZXJhLmdpdGh1Yi5pby9zdGE1NTEvSFcwMS9kYXRhL0VkdWNhdGlvbi5jc3YnLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQoNCg0KI2NsZWFuIGVkdWNhdGlvbiBkYXRhDQplZHUgPC0gZWR1X3JhdyAlPiUgDQogIHN1YnNldCAoLCBjKEZJUFMuQ29kZSwgTGVzcy50aGFuLmEuaGlnaC5zY2hvb2wuZGlwbG9tYS4uMjAxNS4xOSwgSGlnaC5zY2hvb2wuZGlwbG9tYS5vbmx5Li4yMDE1LjE5LCBTb21lLmNvbGxlZ2Uub3IuYXNzb2NpYXRlLnMuZGVncmVlLi4yMDE1LjE5LAlCYWNoZWxvci5zLmRlZ3JlZS5vci5oaWdoZXIuLjIwMTUuMTkpKSAlPiUgICMjcmVtb3ZlIGlycmVsZXZhbnQgY29sdW1ucw0KICByZW5hbWUgKCAiTm9fSFMiID0gTGVzcy50aGFuLmEuaGlnaC5zY2hvb2wuZGlwbG9tYS4uMjAxNS4xOSwgIkhTIiA9IEhpZ2guc2Nob29sLmRpcGxvbWEub25seS4uMjAxNS4xOSwgIkFTX1NvbWVDb2wiID0gU29tZS5jb2xsZWdlLm9yLmFzc29jaWF0ZS5zLmRlZ3JlZS4uMjAxNS4xOSwJIkJTX01vcmUiID0gQmFjaGVsb3Iucy5kZWdyZWUub3IuaGlnaGVyLi4yMDE1LjE5LCBGSVBTID0gRklQUy5Db2RlKSAgIyNyZW5hbWUgZm9yIGVhc2UgYW5kIHNldCBJRCBuYW1lIGZvciBvdXRlciBqb2luDQplZHUkTm9fSFMgPSBnc3ViKCcsJywgJycsIGVkdSROb19IUykgIyNyZW1vdmUgY29tbWFzIGZyb20gbnVtYmVyIHdpdGggY29tbWFzIHNhdmVkIGFzIGNoYXJhY2h0ZXJzDQplZHUkSFMgPSBnc3ViKCcsJywgJycsIGVkdSRIUykNCmVkdSRBU19Tb21lQ29sID0gZ3N1YignLCcsICcnLCBlZHUkQVNfU29tZUNvbCkNCmVkdSRCU19Nb3JlID0gZ3N1YignLCcsICcnLCBlZHUkQlNfTW9yZSkNCmVkdSROb19IUyA9IGFzLm51bWVyaWMoZWR1JE5vX0hTKSAgIyN0cmFuc2Zvcm0gdG8gbnVtZXJpYyB0byBhZ2dyZWdhdGUNCmVkdSRIUyA9IGFzLm51bWVyaWMoZWR1JEhTKQ0KZWR1JEFTX1NvbWVDb2wgPSBhcy5udW1lcmljKGVkdSRBU19Tb21lQ29sKQ0KZWR1JEJTX01vcmUgPSBhcy5udW1lcmljKGVkdSRCU19Nb3JlKQ0KICANCkRUOjpkYXRhdGFibGUoZWR1KQ0KYGBgDQojIyBNZXJnZSBSZWxhdGlvbmFsIERhdGFzZXRzICYgQWdncmVnYXRlIGRhdGENCg0KIyMjIE1lcmdlIHRoZSByZWxhdGlvbmFsIGRhdGFzZXRzIHVzaW5nIGNvdW50eSBGSVBTIGNvZGVzDQoNCk9uY2UgYWxsIGZvdXIgKDQpIHJlbGF0aW9uYWwgZGF0YXNldHMgKGBlZHVgLCBgZWxlY3Rpb25gLCBgcG92ZXJ0eWAsIGFuZCBgdW5lbXBsb3lgKSB3ZXJlIGNyZWF0ZWQsIGEgbmV3IGRhdGFzZXQgbmFtZWQgYGFsbC5kYXRhYCB3YXMgY3JlYXRlZCBieSBjb21wbGV0aW5nIG11bHRpcGxlIGZ1bGwgam9pbiBmdW5jdGlvbnMuICBBbGwgZGF0YXNldHMgd2VyZSBtZXJnZWQgdXNpbmcgdGhlIGNvdW50eSBgRklQU2AgY29kZSBhcyB0aGUgdW5pcXVlIGlkZW50aWZpZXIgY29uc2VydmVkIGFjcm9zcyBhbGwgZGF0YXNldHMuIA0KDQpgYGB7cn0NCiMjbWVyZ2UgZWxlY3Rpb24gZGF0YSAmIGVkdWNhdGlvbiBkYXRhIGFzIGVsZWN0aW9uLmVkdWNhdGlvbiANCmVsZWN0aW9uLmVkdWNhdGlvbiA8LSBmdWxsX2pvaW4gKA0KICB4ID0gZWxlY3Rpb24sDQogIHkgPSBlZHUsDQogIGJ5ID0gIkZJUFMiLA0KICBrZWVwID0gRkFMU0UNCikNCg0KDQojI21lcmdlIGVsZWN0aW9uLmVkdWNhdGlvbiAmIHBvdmVydHkgZGF0YSBhcyBlbGVjdGlvbi5lZHVjYXRpb24ucG92ZXJ0eQ0KZWxlY3Rpb24uZWR1Y2F0aW9uLnBvdmVydHkgPC0gZnVsbF9qb2luKA0KICB4ID0gZWxlY3Rpb24uZWR1Y2F0aW9uLA0KICB5ID0gcG92ZXJ0eSwNCiAgYnkgPSAiRklQUyIsDQogIGtlZXAgPSBGQUxTRQ0KKQ0KDQojI21lcmdlIGVsZWN0aW9uLmVkdWNhdGlvbi5wb3ZlcnR5ICYgdW5lbXBsb3ltZW50IGRhdGEgYXMgYWxsLmRhdGENCmFsbC5kYXRhIDwtIGZ1bGxfam9pbiAoDQogIHggPSBlbGVjdGlvbi5lZHVjYXRpb24ucG92ZXJ0eSwNCiAgeSA9IHVuZW1wbG95LA0KICBieSA9ICJGSVBTIiwNCiAga2VlcCA9IEZBTFNFDQopDQoNCg0KYGBgDQoNCiMjIyBBZ2dyZWdhdGUgdGhlIEVkdWNhdGlvbiBEYXRhIGludG8gJSBIaWdoZXIgRWQNCg0KQXMgdGhlIGVkdWNhdGlvbmFsIGRhdGEgcHJvdmlkZWQgZm9yIGVhY2ggY291bnR5IGNvbnNpc3RlZCBvZiB0aGUgdG90YWwgbnVtYmVyIG9mIHBlcnNvbnMgaW4gZWFjaCBjb3VudHkgdGhhdCByZWNlaXZlZCBlYWNoIG9mIHRoZSBmb3VyIHRpZXJzIG9mIGVkdWNhdGlvbiwgdGhlIGRhdGEgd2FzIGFnZ3JlZ2F0ZWQgdG8gYWxsb3cgZm9yIGNsZWFuZXIgYW5hbHlzaXMgYW5kIGNvbXBhcmlzb24uICBJbiBvcmRlciB0byBhZ2dyZWdhdGUgdGhlIGVkdWNhdGlvbmFsIGRhdGEsIHRoZSBmb3VyIGVkdWNhdGlvbiB2YXJpYWJsZXMgKGBOb19IU2AsIGBIU2AsIGBBU19Tb21lQ29sYCwgJiBgQlNfTW9yZWApIHdlcmUgYWdncmVnYXRlZCB0byBjcmVhdGUgYSBuZXcgdmFyaWFibGUgYEhpZ2hlcl9FZF9QZXJjZW50YCB0byBtZWFzdXJlIHRoZSBwZXJjZW50YWdlIG9mIHRoZSBwb3B1bGF0aW9uIHN1cnZleWVkIHRoYXQgY29tcGxldGVkIGVpdGhlciBzb21lIGNvbGxlZ2UgY3JlZGl0LCBhbiBBc3NvY2lhdGUncyBEZWdyZWUsIGEgQmFjaGVsb3IncyBEZWdyZWUsIG9yIGFkZGl0aW9uYWwgZ3JhZHVhdGUgbGV2ZWwgZGVncmVlcy4gIA0KDQpUaGlzIGhpZ2hlciBlZHVjYXRpb24gbWV0cmljIHdhcyBjcmVhdGVkIGFzIGEgbWVhc3VyZSBvZiB0aGUgYXZlcmFnZSBzb2Npb2Vjb25vbWljIHN0YXR1cyBvZiB0aGUgY291bnRpZXMgYmVpbmcgYW5hbHl6ZWQuDQoNCmBgYHtyfQ0KYWxsLmRhdGEgPC0gYWxsLmRhdGEgICU+JSANCiAgZmlsdGVyKEZJUFMgIT0gMCkgJT4lICMjZmlsdGVyIG91dCB2YWx1ZXMgd2l0aCBubyBhc3NvY2lhdGVkIGNvdW50eSBvciBzdGF0ZSBuYW1lDQogIGZpbHRlcihGSVBTICE9IDEwMDApICU+JSANCiAgbXV0YXRlIChIaWdoZXJfRWRfUGVyY2VudCA9ICgoKGBBU19Tb21lQ29sYCArIGBCU19Nb3JlYCkvKGBOb19IU2ArIGBIU2AgKyBgQVNfU29tZUNvbGAgKyBgQlNfTW9yZWApKSoxMDApKSAgIyMlIG9mIHBvcCB3aXRoIGhpZ2hlciBlZC4NCg0KYGBgDQoNCiMgVmlzdWFsaXppbmcgYW5kIEFuYWx5emluZyB0aGUgRGF0YQ0KDQojIyBNYXBwaW5nIHRoZSBmdWxsIGRhdGENCg0KRm9yIGFuIGluaXRpYWwgdmlzdWFsaXphdGlvbiBvZiB0aGUgZGF0YSBhcyBhIHdob2xlLCB0aGUgYGFsbC5kYXRhYCBkYXRhc2V0IHdhcyBtYXBwZWQgYnkgY291bnR5IHV0aWxpemluZyBhbiBpbnRlcmFjdGl2ZSBsZWFmbGV0IG1hcC4gIER1ZSB0byB0aGUgc2l6ZSBvZiB0aGUgZGF0YXNldCBhbmQgbnVtYmVyIG9mIGNvdW50aWVzLCBjb2xvciBzcGVjaWZpYyBkYXRhIGlzIG5vdCB2aXNpYmxlIHVudGlsIHRoZSBtYXAgaXMgem9vbWVkIGluIHRvIHRoZSBhcHByb3ByaWF0ZSBjb3VudHkgbGV2ZWwuICBVbnRpbCB6b29tZWQgaW4gdGhlIGNvbG9yIHNjYWxlIChncmVlbiB0byByZWQpIHJlcHJlc2VudHMgdGhlIG51bWJlciBvZiBjb3VudGllcyBuZXN0ZWQgaW4gdGhhdCBncm91cCB1bnRpbCB0aGUgbWFwIGlzIHpvb21lZCBpbiBmdXJ0aGVyLiAgT25jZSBmdWxseSB6b29tZWQgaW4gdGhlIGNvbG9yIG9mIHRoZSA8Yj51bm51bWJlcmVkIGNpcmNsZXM8L2I+IChyZWQgYW5kIGJsdWUpIHJlcHJlc2VudCB0aGUgd2lubmluZyBwYXJ0eSAoUmVwdWJsaWNhbiBhbmQgRGVtb2NyYXQgcmVzcGVjdGl2ZWx5KSBpbiBlYWNoIGNvdW50eSBmb3IgdGhlIDIwMjAgcHJlc2lkZW50aWFsIGVsZWN0aW9uLg0KDQpgYGB7cn0NCg0KY291bnR5X2RhdGFfcmF3IDwtIHNmOjpyZWFkX3NmKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcGxvdGx5L2RhdGFzZXRzL21hc3Rlci9nZW9qc29uLWNvdW50aWVzLWZpcHMuanNvbiIpICMjcHVsbCBpbiBtYXAgb2YgRklQUyBjb2RlcyANCg0KRklQU2NvbnZlcnRfcmF3IDwtIHNmOjpyZWFkX3NmKCJodHRwczovL25sZXBlcmEuZ2l0aHViLmlvL3N0YTU1MS9IVzAxL2RhdGEvZmlwczJnZW9jb2RlLmNzdiIpICMjcHVsbCBpbiBrZXkgb2YgRklQUyBjb2RlcyB0byBsYXQvbG9uZw0KDQpjb3VudHlfZGF0YSA8LSBjb3VudHlfZGF0YV9yYXcgJT4lICAjY2xlYW4gY291bnR5IGRhdGEgdG8gbGlzdCBGSVBTIGFzIG51bWVyaWMgJiBtYXRjaCBuYW1lIHRvIGtleSBmb3Igam9pbg0KICBtdXRhdGUgKGlkID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoaWQpKSkgJT4lIA0KICByZW5hbWUgKEZJUFMgPSBpZCkNCg0KRklQU2NvbnZlcnQgPC0gRklQU2NvbnZlcnRfcmF3ICU+JSAgDQogIG11dGF0ZSAoZmlwcyA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGZpcHMpKSwgbG9uID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobG9uKSksIGxhdCA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGxhdCkpKSAlPiUgDQogIHJlbmFtZSAoRklQUyA9IGZpcHMsIExvbmdpdHVkZSA9IGxvbiwgTGF0aXR1ZGUgPSBsYXQpDQoNCmFsbC5kYXRhLmpvaW4gPC0gZnVsbF9qb2luKA0KICB4ID0gYWxsLmRhdGEsDQogIHkgPSBGSVBTY29udmVydCwNCiAgYnkgPSAiRklQUyIsDQogIGtlZXAgPSBGQUxTRQ0KKSAlPiUgDQogIHVuZ3JvdXAoKQ0KYGBgDQoNCjxoMj4gSW50ZXJhY3RpdmUgTWFwIG9mIENvdW50eSBEYXRhIDwvaDI+DQoNCmBgYHtyfQ0KcGFsIDwtIGNvbG9yRmFjdG9yKGMoImJsdWUiLCAicmVkIiksIGRvbWFpbiA9IGMoIlJFUFVCTElDQU4iLCAiREVNT0NSQVQiKSkNCg0KdGl0bGUgPC0gIg0KPHN0eWxlPg0KICAuY3VzdG9tLXRpdGxlIHsNCiAgICBjb2xvcjogd2hpdGU7DQogICAgcGFkZGluZzogMHB4Ow0KICAgIGJvcmRlci1yYWRpdXM6IDBweDsNCiAgICB0ZXh0LWFsaWduOiByaWdodDsNCiAgfQ0KPC9zdHlsZT4NCkVsZWN0aW9uIFJlc3VsdHMsIEVkdWNhdGlvbiBSYXRlcywgVW5lbXBsb3ltZW50IFJhdGVzICYgUG92ZXJ0eSBSYXRlcw0KPGJyPlpvb20gaW4gdG8gdmlldyBlYWNoIGNvdW50eSBpbmRpdmlkdWFsbHkNCjxicj5TZWxlY3QgYSBjb3VudHkncyBjaXJjbGUgdG8gdmlldyBmdWxsIGRhdGEiDQoNCmxlYWZsZXQoKSAlPiUgDQogIHNldFZpZXcobG5nPS05OC41Nzk1LCBsYXQ9MzkuODI4Mywgem9vbSA9IDQpICU+JSAjI3NldCB2aWV3IHRvIG1pZCBVUw0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLkRhcmtNYXR0ZXIpICU+JSAgIyNzZXQgbWFwIHRvIGRhcmsgbW9kZQ0KICBhZGRDb250cm9sKGh0bWwgPSB0aXRsZSwgDQogICAgICAgICAgICAgcG9zaXRpb24gPSAidG9wcmlnaHQiLCANCiAgICAgICAgICAgICBjbGFzc05hbWUgPSAiY3VzdG9tLXRpdGxlIikgJT4lIA0KICBhZGRQb2x5Z29ucyhkYXRhID0gY291bnR5X2RhdGEsICAjI2FkZCBGSVBTIHBvbHlnb25zDQogICAgICAgICAgICAgIGNvbG9yID0gInllbGxvdyIsDQogICAgICAgICAgICAgIGZpbGwgPSBGQUxTRSwNCiAgICAgICAgICAgICAgd2VpZ2h0ID0gMC4yNSkgJT4lIA0KICBhZGRDaXJjbGVNYXJrZXJzKGRhdGEgPSBhbGwuZGF0YS5qb2luLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gfnBhbChwYXJ0eSksDQogICAgICAgICAgICAgICAgICAgcmFkaXVzID0gMjAsDQogICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjUsDQogICAgICAgICAgICAgICAgICAgcG9wdXAgPSB+cG9wdXBUYWJsZShhbGwuZGF0YSksDQogICAgICAgICAgICAgICAgICAgY2x1c3Rlck9wdGlvbnMgPSBtYXJrZXJDbHVzdGVyT3B0aW9ucyhtYXhDbHVzdGVyUmFkaXVzID0gNTApKQ0KICANCiAgDQpgYGANCg0KIyMgUGxvdCB2YXJpYWJsZSBkaXN0cmlidXRpb24NCg0KQmVmb3JlIGNvbXBsZXRpbmcgYW55IGRhdGEgYW5hbHlzaXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgdGhyZWUgbnVtZXJpYyB2YXJpYWJsZXMgb2YgaW50ZXJlc3Qgd2FzIHJldmlld2VkLCBjb250cm9sbGluZyBmb3IgdGhlIHRoZSB3aW5uaW5nIHBhcnR5IChSZXB1YmxpY2FuIG9yIERlbW9jcmF0KSBpbiBlYWNoIGNvdW50eSBmb3IgdGhlIDIwMjAgcHJlc2lkZW50aWFsIGVsZWN0aW9uLg0KDQpCb3RoIHVuZW1wbG95bWVudCBhbmQgaGlnaGVyIGVkdWNhdGlvbiByYXRlcyBhcHBlYXIgdG8gaGF2ZSBub3JtYWwgZGlzdHJpYnV0aW9ucyB3aGlsZSBwb3ZlcnR5IHJhdGVzIGFwcGVhciB0byBoYXZlIGNsb3NlciB0byBhIGdhbW1hIGRpc3RyaWJ1dGlvbi4gIEEgZ3JlYXRlciBmcmVxdWVuY3kgb2YgY291bnRpZXMgd2l0aCBkZW1vY3JhdGljIGNhbmRpZGF0ZSB3aW5uZXJzIHdhcyBzZWVuIGZvciBhbGwgdGhyZWUgKDMpIHZhcmlhYmxlcyBpbiBxdWVzdGlvbi4gDQpgYGB7cn0NCg0KZ2dwbG90IChhbGwuZGF0YSwgYWVzKHggPSBgVW5lbXBsb3ltZW50X1JhdGUgKCUpYCwgZmlsbCA9IGBwYXJ0eWApKSArDQogIGdlb21faGlzdG9ncmFtKGluaGVyaXQuYWVzID0gVFJVRSwgY29sb3IgPSAiYmxhY2siKSArDQogIGdndGl0bGUgKCJEaXN0cmlidXRpb24gb2YgVW5lbXBsb3ltZW50IFJhdGVzIGJ5IENvdW50eSBFbGVjdGlvbiBXaW5uZXIiKSArDQogIHhsYWIgKCJDb3VudHkgVW5lbXBsb3ltZW50IFJhdGUgKHgpDQogICAgICAgIFslIG9mIENvdW50eSBQb3AuXSIpICsgDQogIHlsYWIgKCJDb3VudGllcyBXLyBVbmVtcGxveW1lbnQgUmF0ZSA9IHgiKSAgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJibHVlIiwgInJlZCIpKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44LCAwLjgpKQ0KDQpnZ3Bsb3QgKGFsbC5kYXRhLCBhZXMoeCA9IGBQb3ZlcnR5X1JhdGUgKCUpYCwgZmlsbCA9IGBwYXJ0eWApKSArDQogIGdlb21faGlzdG9ncmFtKGluaGVyaXQuYWVzID0gVFJVRSwgY29sb3IgPSAiYmxhY2siKSArIA0KICBnZ3RpdGxlICgiRGlzdHJpYnV0aW9uIG9mIFBvdmVydHkgUmF0ZXMgYnkgQ291bnR5IEVsZWN0aW9uIFdpbm5lciIpICsgDQogIHhsYWIgKCJDb3VudHkgUG92ZXJ0eSBSYXRlICh4KQ0KICAgICAgICBbJSBvZiBDb3VudHkgUG9wLl0iKSArDQogIHlsYWIgKCJDb3VudGllcyBXLyBQb3ZlcnR5IFJhdGUgPSB4IikgICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiYmx1ZSIsICJyZWQiKSkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuOCwgMC44KSwgaGVpZ2h0ID0gIjIwMHB4IikNCg0KZ2dwbG90IChhbGwuZGF0YSwgYWVzKHggPSBgSGlnaGVyX0VkX1BlcmNlbnRgLCBmaWxsID0gYHBhcnR5YCkpICsgDQogIGdlb21faGlzdG9ncmFtKGluaGVyaXQuYWVzID0gVFJVRSwgY29sb3IgPSAiYmxhY2siKSArIA0KICBnZ3RpdGxlICgiRGlzdHJpYnV0aW9uIG9mIEhpZ2hlciBFZHVjYXRpb24gUmF0ZXMgYnkgQ291bnR5IEVsZWN0aW9uIFdpbm5lciIpICsgDQogIHhsYWIgKCJDb3VudHkgSGlnaGVyIEVkLiBSYXRlICh4KQ0KICAgICAgICBbJSBvZiBDb3VudHkgUG9wLl0gIikgKyANCiAgeWxhYiAoIkNvdW50aWVzIFcvIEhpZ2hlciBFZC4gUmF0ZSA9IHgiKSAgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJibHVlIiwgInJlZCIpKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44LCAwLjgpKQ0KDQpgYGANCg0KIyMgUGxvdCBSZWxhdGlvbnNoaXAgQmV0d2VlbiBOdW1lcmljIFZhcmlhYmxlcw0KDQpUbyBkZXRlcm1pbmUgdGhlIHBvdGVudGlhbCByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlIHRocmVlIG51bWVyaWMgdmFyaWFibGVzIG9mIGludGVyZXN0IChgVW5lbXBsb3ltZW50IFJhdGVgLCBgUG92ZXJ0eSBSYXRlYCwgYW5kIGBIaWdoZXIgRWR1Y2F0aW9uIFJhdGVgKSB3ZXJlIHBsb3R0ZWQgYWdhaW5zdCBlYWNoIG90aGVyIGFuZCByZXZpZXdlZCB1dGlsaXppbmcgYSBiYXNpYyBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBmb3IgdGhlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGRhdGEgYW5kIGEgR0xNIGdhbW1hIHJlZ3Jlc2lvbiBtb2RlbCBmb3IgdGhlIGdhbW1hIGRpc3RyaWJ1dGVkIGRhdGEuDQpgYGB7cn0NCmdncGxvdChkYXRhID0gYWxsLmRhdGEsIGFlcyh4ID1hbGwuZGF0YSRgVW5lbXBsb3ltZW50X1JhdGUgKCUpYCwgeT1hbGwuZGF0YSRgUG92ZXJ0eV9SYXRlICglKWAsIGNvbG9yPWBwYXJ0eWApKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjI1KSArDQogICAgZ2d0aXRsZSAoIlVuZW1wbG95bWVudCBSYXRlcyB2cy4gUG92ZXJ0eSBSYXRlcyBieSBFbGVjdGlvbiBXaW5uaW5nIFBhcnR5IikgKyANCiAgICB4bGFiICgiQ291bnR5IFVuZW1wbG95bWVudCBSYXRlIFslIG9mIENvdW50eSBQb3AuXSAoeCkiKSArIA0KICAgIHlsYWIgKCJDb3VudHkgUG92ZXJ0eSBSYXRlIFslIG9mIENvdW50eSBQb3AuXSAoeSkiKSAgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYmx1ZSIsICJyZWQiKSkgKw0KICBzdGF0X3Ntb290aChtZXRob2QgPSBsbSwgc2U9RkFMU0UsIHNpemUgPSAwLjEpIA0KDQpgYGANCg0KYGBge3J9DQpwb3ZfdW5lbSA8LSBsbShgUG92ZXJ0eV9SYXRlICglKWB+YFVuZW1wbG95bWVudF9SYXRlICglKWAgLCBkYXRhID0gYWxsLmRhdGEpDQpzdW1tYXJ5KHBvdl91bmVtKQ0KDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGFsbC5kYXRhLCBhZXMoeCA9YWxsLmRhdGEkYEhpZ2hlcl9FZF9QZXJjZW50YCwgeT1hbGwuZGF0YSRgUG92ZXJ0eV9SYXRlICglKWAsIGNvbG9yPWBwYXJ0eWApKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjI1KSArDQogICAgZ2d0aXRsZSAoIlBlcmNlbnQgb2YgUG9wdWxhdGlvbiB3LyBIaWdoZXIgRWR1Y2F0aW9uIHZzLg0KICAgICAgICAgICAgIFBvdmVydHkgUmF0ZXMgYnkgRWxlY3Rpb24gV2lubmluZyBQYXJ0eSIpICsgDQogICAgeGxhYiAoIkNvdW50eSBIaWdoZXIgRWQuIFJhdGUgWyUgb2YgQ291bnR5IFBvcC5dICh4KSIpICsgDQogICAgeWxhYiAoIkNvdW50eSBQb3ZlcnR5IFJhdGUgWyUgb2YgQ291bnR5IFBvcC5dICh5KSIpICArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibHVlIiwgInJlZCIpKSArDQogIHN0YXRfc21vb3RoKG1ldGhvZCA9IGdsbSwgc2U9RkFMU0UsIHNpemUgPSAwLjEpIA0KDQpgYGANCg0KYGBge3J9DQpoaWdoZWRfcG92IDwtIGdsbShgSGlnaGVyX0VkX1BlcmNlbnRgfmBQb3ZlcnR5X1JhdGUgKCUpYCwgZGF0YSA9IGFsbC5kYXRhKQ0Kc3VtbWFyeShoaWdoZWRfcG92KQ0KDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGFsbC5kYXRhLCBhZXMoeCA9YWxsLmRhdGEkYEhpZ2hlcl9FZF9QZXJjZW50YCwgeT1hbGwuZGF0YSRgVW5lbXBsb3ltZW50X1JhdGUgKCUpYCwgY29sb3I9YHBhcnR5YCkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMjUpICsNCiAgICBnZ3RpdGxlICgiUGVyY2VudCBvZiBQb3B1bGF0aW9uIHcvIEhpZ2hlciBFZHVjYXRpb24gdnMuDQogICAgICAgICAgICAgVW5lbXBsb3ltZW50IFJhdGVzIGJ5IEVsZWN0aW9uIFdpbm5pbmcgUGFydHkiKSArIA0KICAgIHhsYWIgKCJDb3VudHkgSGlnaGVyIEVkLiBSYXRlIFslIG9mIENvdW50eSBQb3AuXSAoeCkiKSArIA0KICAgIHlsYWIgKCJDb3VudHkgVW5lbXBsb3ltZW50IFJhdGUgWyUgb2YgQ291bnR5IFBvcC5dICh5KSIpICArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibHVlIiwgInJlZCIpKSArDQogIHN0YXRfc21vb3RoKG1ldGhvZCA9IGxtLCBzZT1GQUxTRSwgc2l6ZSA9IDAuMSkgDQoNCmBgYA0KDQpgYGB7cn0NCmhpZ2hlZF91bmVtIDwtIGxtKGBIaWdoZXJfRWRfUGVyY2VudGB+YFVuZW1wbG95bWVudF9SYXRlICglKWAsIGRhdGEgPSBhbGwuZGF0YSkNCnN1bW1hcnkoaGlnaGVkX3VuZW0pDQoNCmBgYA0KDQojIENvbmNsdXNpb25zDQoNCldoaWxlIGFsbCB0aHJlZSBpbnZlc3RpZ2F0ZWQgcG90ZW50aWFsIGNvcnJlbGF0aW9ucyBpbmRpY2F0ZWQgYSBoaWdoIGxldmVsIG9mIHN0YXRpc3RpYyBzaWduaWZpY2FuY2Ugd2l0aCBwIHZhbHVlcyB3ZWxsIGJlbG93IDAuMDUsIGJvdGggdGhlIGBVbmVtcGxveW1lbnQgUmF0ZXMgdnMuIFBvdmVydHkgUmF0ZXMgYnkgRWxlY3Rpb24gV2lubmluZyBQYXJ0eWAgYW5kIGBQZXJjZW50IG9mIFBvcHVsYXRpb24gdy8gSGlnaGVyIEVkdWNhdGlvbiB2cy4gVW5lbXBsb3ltZW50IFJhdGVzIGJ5IEVsZWN0aW9uIFdpbm5pbmcgUGFydHlgIG1vZGVscyBpbGx1c3RyYXRlZCBhIHBvb3IgZml0IHdpdGggdmVyeSBsb3cgUiBzcXVhcmVkIHZhbHVlcy4gIFRoZSBgUGVyY2VudCBvZiBQb3B1bGF0aW9uIHcvIEhpZ2hlciBFZHVjYXRpb24gdnMuIFBvdmVydHkgUmF0ZXMgYnkgRWxlY3Rpb24gV2lubmluZyBQYXJ0eWAgYWxzbyBpbGx1c3RyYXRlZCBhIHBvb3IgZml0IGJ1dCBoYWQgdGhlIGhpZ2hlc3QgciBzcXVhcmVkIHZhbHVlIGluZGljYXRpbmcgcmVkdWNlZCB2YXJpYW5jZSBpbiB0aGlzIG1vZGVsLiBObyBjbHVzdGVyaW5nIHdhcyBub3RlZCBhbG9uZyB0aGUgcGFydHkgdmFyaWFibGVzLiANCg0KT3ZlcmFsbCBhIGNvcnJlbGF0aW9uIGJldHdlZW4gdW5lbXBsb3ltZW50IHJhdGVzLCBwb3ZlcnR5IHJhdGVzLCBoaWdoZXIgZWR1Y2F0aW9uIHJhdGVzLCBhbmQgY291bnR5IHdpbm5pbmcgcGFydHkgd2FzIG5vdCBpbGx1c3RyYXRlZC4g